package main

import (
	"fmt"
	"io"
	"math"
	"net/http"
)

const (
	angle  = math.Pi / 6
	width  = 500
	height = 500
)

var sin30, cos30 = math.Sin(angle), math.Cos(angle)

func draw(w io.Writer) {
	x1, y1 := 0.0, 0.0
	x2, y2 := 0.0, 2.0
	x3, y3 := 4.0, 2.0
	x4, y4 := 4.0, 0.0
	x5, y5 := 0.0, 0.0
	x6, y6 := 0.0, 2.0
	x7, y7 := 4.0, 2.0
	x8, y8 := 4.0, 0.0
	z1, z2 := 0.0, 1.0

	xx1, yy1 := project(x1, y1, z1)
	xx2, yy2 := project(x2, y2, z1)
	xx3, yy3 := project(x3, y3, z1)
	xx4, yy4 := project(x4, y4, z1)
	xx5, yy5 := project(x5, y5, z2)
	xx6, yy6 := project(x6, y6, z2)
	xx7, yy7 := project(x7, y7, z2)
	xx8, yy8 := project(x8, y8, z2)

	fmt.Fprintf(w, "<svg xmlns='http://www.w3.org/2000/svg' style='stroke:red; fill:#FFFF99; stroke-width:2.7' width='%g' height='%g'>\n", width, height)
	io.WriteString(w, polygon(xx1, yy1, xx2, yy2, xx3, yy3, xx4, yy4)) // 底面
	io.WriteString(w, polygon(xx1, yy1, xx2, yy2, xx6, yy6, xx5, yy5)) // 背面
	io.WriteString(w, polygon(xx1, yy1, xx4, yy4, xx8, yy8, xx5, yy5)) // 右侧
	io.WriteString(w, polygon(xx2, yy2, xx3, yy3, xx7, yy7, xx6, yy6)) // 左侧
	io.WriteString(w, polygon(xx3, yy3, xx4, yy4, xx8, yy8, xx7, yy7)) // 正面
	io.WriteString(w, polygon(xx5, yy5, xx6, yy6, xx7, yy7, xx8, yy8)) // 顶面
	fmt.Fprintf(w, "</svg>\n")
}

// 绘制多边形
func polygon(x1, y1, x2, y2, x3, y3, x4, y4 float64) string {
	var svg string
	scale := 100.0
	svg = fmt.Sprintf("<polygon points='%g,%g %g,%g %g,%g %g,%g' />\n",
		width/2+x1*scale, height/2+y1*scale,
		width/2+x2*scale, height/2+y2*scale,
		width/2+x3*scale, height/2+y3*scale,
		width/2+x4*scale, height/2+y4*scale)
	return svg
}

// 投影函数
func project(x, y, z float64) (float64, float64) {
	xx := x*cos30 - y*cos30
	yy := x*sin30 + y*sin30 - z
	return xx, yy
}

func handle(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "image/svg+xml")
	draw(w)
}

func main() {
	http.HandleFunc("/", handle)
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		fmt.Printf("%v", err)
	}
}
